
#include "SQLIdentifierExpr.h"

#include "../../../utils/instanceof.h"
#include "../../../utils/FnvHash.h"
#include "../../../utils/StringUtils.h"
#include "../../SQLUtils.h"
#include "../../visitor/SQLASTVisitor.h"
#include "../SQLParameter.h"
#include "../SQLDeclareItem.h"
#include "../statement/SQLSelectItem.h"
#include "../statement/SQLColumnDefinition.h"

string_ptr SQLIdentifierExpr::class_ = make_string_ptr("SQLIdentifierExpr");

SQLIdentifierExpr::SQLIdentifierExpr()
{

  // std::cout << "\t\t\t\t\t\t" <<  __FILE__ << ": " << __LINE__ << ", in SQLIdentifierExpr::SQLIdentifierExpr, constructor" << std::endl;
}

SQLIdentifierExpr::~SQLIdentifierExpr()
{
  // std::cout << "\t\t\t\t\t\t" <<  __FILE__ << ": " << __LINE__ << ", in SQLIdentifierExpr::~SQLIdentifierExpr, destructor step 1" << std::endl;
}

SQLIdentifierExpr::SQLIdentifierExpr(string_ptr theName)
{
  name = theName;
}

string_ptr SQLIdentifierExpr::getSimleName()
{
  return name;
}

string_ptr SQLIdentifierExpr::getName()
{
  return name;
}

void SQLIdentifierExpr::setName(string_ptr theName)
{
  name = name;
  lowerName = make_string_ptr("");
}

string_ptr SQLIdentifierExpr::getLowerName()
{

  if (lowerName == make_string_ptr("") && name != make_string_ptr(""))
  {
    lowerName = StringUtils::toLower(lowerName);
    // lowerName = name.toLowerCase();
  }

  return lowerName;
}

void SQLIdentifierExpr::setLowerName(string_ptr theLowerName)
{
  lowerName = theLowerName;
}

void SQLIdentifierExpr::output(std::stringstream *buf)
{
  (*buf) << *(name.get());
  // buf.append(name);
}

void SQLIdentifierExpr::accept0(SQLASTVisitor_ptr visitor)
{
  visitor->visit(SharedObject(SQLIdentifierExpr));

  visitor->endVisit(SharedObject(SQLIdentifierExpr));
}

// int SQLIdentifierExpr::hashCode() {
// final int prime = 31;
// int result = 1;
// result = prime * result + ((name == NULL) ? 0 : name.hashCode());
// return result;
//}

// BOOL_ptr SQLIdentifierExpr::equals(Object obj) {
// if (this == obj) {
// return BOOL::TRUE;
//}
// if (obj == NULL) {
// return BOOL::FALSE;
//}
// if (!(obj instanceof SQLIdentifierExpr)) {
// return BOOL::FALSE;
//}
// SQLIdentifierExpr other = (SQLIdentifierExpr) obj;
// if (name == NULL) {
// if (other.name != NULL) {
// return BOOL::FALSE;
//}
//} else if (!name.equals(other.name)) {
// return BOOL::FALSE;
//}
// return BOOL::TRUE;
//}

string_ptr SQLIdentifierExpr::getSimpleName() { return name; };

// SQLName_ptr SQLIdentifierExpr::clone(){};
SQLObject_ptr SQLIdentifierExpr::clone()
{
  SQLObject_ptr clone_tmp = SQLIdentifierExpr_ptr(new SQLIdentifierExpr());
  SQLIdentifierExpr_ptr clone_res = std::dynamic_pointer_cast<SQLIdentifierExpr>(clone_tmp);

  return clone_res;
}

long SQLIdentifierExpr::nameHashCode64()
{
  return hashCode64();
};

long SQLIdentifierExpr::hashCode64()
{
  if (hashCode64_ == 0 && name != nullptr)
  {
    hashCode64_ = FnvHash::hashCode64(name);
  }
  return hashCode64_;
};

// SQLTableSource_ptr  SQLIdentifierExpr::getResolvedTableSource() {
// 	if (instanceof<SQLObject, SQLTableSource>(resolvedOwnerObject)) {
// 		return dynamic_cast<SQLTableSource_ptr >(resolvedOwnerObject);
// 	}
// 	return NULL;
// }

BOOL_ptr SQLIdentifierExpr::nameEquals(string_ptr name)
{
  return SQLUtils::nameEquals(this->name, name) ? BOOL::TRUE : BOOL::FALSE;
}

string_ptr SQLIdentifierExpr::normalizedName()
{
  return SQLUtils::normalize(name);
}

SQLTableSource_ptr SQLIdentifierExpr::getResolvedTableSource()
{
  if (instanceof <SQLObject, SQLTableSource>(resolvedOwnerObject))
  {
    return std::dynamic_pointer_cast<SQLTableSource>(resolvedOwnerObject);
  }

  return nullptr;
}
void SQLIdentifierExpr::setResolvedTableSource(SQLTableSource_ptr resolvedTableSource)
{
  this->resolvedOwnerObject = resolvedTableSource;
}
SQLObject_ptr SQLIdentifierExpr::getResolvedOwnerObject()
{
  return resolvedOwnerObject;
}

void SQLIdentifierExpr::setResolvedOwnerObject(SQLObject_ptr resolvedOwnerObject)
{
  this->resolvedOwnerObject = resolvedOwnerObject;
}
void SQLIdentifierExpr::setResolvedColumn(SQLColumnDefinition_ptr resolvedColumn)
{
  this->resolvedColumn = resolvedColumn;
}

void SQLIdentifierExpr::setResolvedColumn(SQLSelectItem_ptr selectItem)
{
  this->resolvedColumn = selectItem;
}

SQLSelectItem_ptr SQLIdentifierExpr::getResolvedSelectItem()
{
  if (instanceof <SQLObject, SQLSelectItem>(resolvedColumn))
  {
    return std::dynamic_pointer_cast<SQLSelectItem>(resolvedColumn);
  }

  return nullptr;
}

SQLObject_ptr SQLIdentifierExpr::getResolvedColumnObject()
{
  return resolvedColumn;
}
void SQLIdentifierExpr::setResolvedDeclareItem(SQLDeclareItem_ptr resolvedDeclareItem)
{
  this->resolvedColumn = resolvedDeclareItem;
}
void SQLIdentifierExpr::setResolvedParameter(SQLParameter_ptr resolvedParameter)
{
  this->resolvedColumn = std::dynamic_pointer_cast<SQLObject>(resolvedParameter);
}

SQLObject_ptr SQLIdentifierExpr::getResolvedColumn()
{
  if (instanceof <SQLObject, SQLColumnDefinition>(resolvedColumn))
  {
    return std::dynamic_pointer_cast<SQLColumnDefinition>(resolvedColumn);
  }

  if (instanceof <SQLObject, SQLSelectItem>(resolvedColumn))
  {
    SQLSelectItem_ptr selectItem = std::dynamic_pointer_cast<SQLSelectItem>(resolvedColumn);
    SQLExpr_ptr expr = selectItem->getExpr();
    if (instanceof <SQLExpr, SQLIdentifierExpr>(expr))
    {
      return (std::dynamic_pointer_cast<SQLIdentifierExpr>(expr))->getResolvedColumn();
    }
    else if (instanceof <SQLExpr, SQLPropertyExpr>(expr))
    {
      return (std::dynamic_pointer_cast<SQLPropertyExpr>(expr))->getResolvedColumn();
    }
  }

  return nullptr;
}

SQLParameter_ptr SQLIdentifierExpr::getResolvedParameter()
{
  if (instanceof <SQLObject, SQLParameter>(resolvedColumn))
  {
    return std::dynamic_pointer_cast<SQLParameter>(this->resolvedColumn);
  }
  return nullptr;
}

// void SQLIdentifierExpr::setResolvedParameter(SQLParameter_ptr resolvedParameter)
// {
//   this->resolvedColumn = std::dynamic_pointer_cast<SQLObject>(resolvedParameter);
// }
SQLDeclareItem_ptr SQLIdentifierExpr::getResolvedDeclareItem()
{
  if (instanceof <SQLObject, SQLDeclareItem>(resolvedColumn))
  {
    return std::dynamic_pointer_cast<SQLDeclareItem>(this->resolvedColumn);
  }
  return nullptr;
}

SQLIdentifierExpr_ptr SQLIdentifierExpr::simplify()
{
  string_ptr normalized = SQLUtils::normalize(name);
  if (normalized != name)
  {
    return SQLIdentifierExpr_ptr(new SQLIdentifierExpr(normalized, hashCode64_));
  }
  return SharedObject(SQLIdentifierExpr);
}
